#ifndef CCourrierH
#define CCourrierH
//---------------------------------------------------------------------------
#include "uListeLangues.h" //Pour IDLangue

#include "Outils.h"
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
#define NOM_DLL_EDITEUR "EICEdito.dll"
#define SANS_CONTRAINTE -1

enum eErrCourriers
   {
   eOk = 0,       // Aucune erreur
   eInconnu,      // Erreur inconnue
   eCoorInit,     // Les coordonnés de dossiers ont changés
   eErrMigration  // Erreur pendant la migration
   };

enum IDOrientation
  {
  eOrLibre = 0,   //Orientation libre
  eOrPortrait,    //Orientation en mode portrait
  eOrPaysage,     //Orientation en mode paysage
  NB_ORIENTATIONS //Toutes les orientations
  };

enum eNivModele
   {
   eNivAucun    = -2,
   eNivPro      = -1, //Désigne le fichier PRO
   eNivPrimaire = 0,  //Désigne le fichier RTF du commun
   eNiv1,             //Désigne le 1er modèle secondaire du dossier (fichier .rtf)
   eNiv2,             //Désigne le 2nd modèle secondaire du dossier (fichier .rt2)
   eNiv3,             //Désigne le 3e  modèle secondaire du dossier (fichier .rt3)
   eNiv4,
   eNiv5,
   eNiv6,
   eNiv7,
   eNiv8,
   eNiv9,
   };

enum TActionModele
   {
   eAM_FichierModifier,    //Le fichier modèle a été modifié (associé à une structure TDescriptifFichier)
   eAM_ModeleAjouter,      //Le modèle a été ajouté (associé à une structure TDescriptifModele)
   eAM_ModeleRenommer,     //Le modèle a été renommé (associé à une structure TDescriptifModeleRenomme)
   eAM_ModeleSupprimer,    //Le modèle a été supprimé (associé à une structure TDescriptifModele)
   eAM_FichierSupprimer,   //Le fichier modèle a été supprimé (associé à une structure TDescriptifFichier)
   };

struct TDescriptifFichier
   {
   AnsiString    aLogiciel;
   AnsiString    aCategorie;
   AnsiString    aLibelle;
   IDLangue      eLangue;
   IDOrientation eOrientation;
   };

enum TCol {colLogiciel, colCateg, colNom, colPapierEnTete, colOrigine, colParam1, colParam2, colNonDefinie};

struct TContrainteTaille
   {
   int iHEnTeteMax;     //Hauteur maximum de l'en-tête (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   int iHCorpsMax;      //Hauteur maximum du corps (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   int iHPiedMax;       //Hauteur maximum du pied de page (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte

   int iMargeG;         //Valeur de la marge de gauche (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   int iMargeD;         //Valeur de la marge de droite (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   int iMargeH;         //Valeur de la marge de haut (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   int iMargeB;         //Valeur de la marge de bas  (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   };

typedef bool __fastcall (__closure *GetValueOfVarEvent)(const AnsiString &aVariable, AnsiString *aValeur);
typedef void __fastcall (__closure *GetDescriptionModele)(const AnsiString &aLogiciel,
                                                          const AnsiString &aCategorie,
                                                          const AnsiString &aLibelle,
                                                          AnsiString *aCommentaire);

typedef bool __fastcall (__closure *TFctQueryActionModele)(TActionModele eActionModele, void *sAction, bool *bQuestionAutomatique);
typedef void __fastcall (__closure *TFctActionModele)(TActionModele eActionModele, void *sAction);
typedef bool __fastcall (__closure *TFctModeleIsVisible)(const AnsiString &aLogiciel,
                                                         const AnsiString &aCategorie,
                                                         const AnsiString &aLibelle);

class PACKAGE_OUTILS TContrainteTailleRichEdit : public TPersistent
   {
   private :
      int m_iHEnTeteMax;
      int m_iHCorpsMax;
      int m_iHPiedMax;

      int m_iMargeG;
      int m_iMargeD;
      int m_iMargeH;
      int m_iMargeB;

      TNotifyEvent m_OnHauteurChange;
      TNotifyEvent m_OnMargeChange;

      void __fastcall SetHEnTeteMax (int iHEnTeteMax);
      void __fastcall SetHCorpsMax (int iHCorpsMax);
      void __fastcall SetHPiedMax (int iHPiedMax);
      void __fastcall SetMargeG (int iMargeG);
      void __fastcall SetMargeD (int iMargeD);
      void __fastcall SetMargeH (int iMargeH);
      void __fastcall SetMargeB (int iMargeB);

   public :
      __fastcall TContrainteTailleRichEdit(TNotifyEvent OnHauteurChange, TNotifyEvent OnMargeChange);

  __published :
      __property int HauteurEnTeteMax = {read=m_iHEnTeteMax, write=SetHEnTeteMax, default = SANS_CONTRAINTE}; //Hauteur maximum de l'en-tête (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
      __property int HauteurCorpsMax  = {read=m_iHCorpsMax , write=SetHCorpsMax , default = SANS_CONTRAINTE}; //Hauteur maximum du corps (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
      __property int HauteurPiedMax   = {read=m_iHPiedMax  , write=SetHPiedMax  , default = SANS_CONTRAINTE}; //Hauteur maximum du pied de page (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte

      __property int MargeG           = {read=m_iMargeG , write=SetMargeG , default = SANS_CONTRAINTE}; //Valeur de la marge de gauche (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
      __property int MargeD           = {read=m_iMargeD , write=SetMargeD , default = SANS_CONTRAINTE}; //Valeur de la marge de droite (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
      __property int MargeH           = {read=m_iMargeH , write=SetMargeH , default = SANS_CONTRAINTE}; //Valeur de la marge du haut   (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
      __property int MargeB           = {read=m_iMargeB , write=SetMargeB , default = SANS_CONTRAINTE}; //Valeur de la marge de bas    (en mm) Mettre à SANS_CONTRAINTE pour éviter la contrainte
   };

class tsConfigBPL
   {
   public : //Variables de configuration de l'éditeur
      char* szLogiciel;    // Nom de l'assistant (Ex:CO)
      char* szCategorie;   // Nom de la catégorie du courrier, si NULL => toutes les catégories
                               // SI Logiciel = NULL ALORS la catégorie est NULL
      char* szCategorieVariables;   // Nom des catégories de variables à utiliser. La catégorie précédée
                                    // du caractère * est la catégorie par défaut.
                                    // Si la chaine est vide OU si elle ne contient que la catégorie par défaut => toutes les catégories seront accessibles
                                    //
                                    // SI Logiciel = NULL ALORS la catégorie des variables est NULL
      IDLangue eLangue;   //Langue dans laquelle les modèles seront gérés
      IDOrientation eOrientation;   //Orientation imposée sur les modèles
      unsigned long nCoorDossier;     //Numéro lié à la configuration des émetteurs/destinataires liés à ce dossier
      bool bChangerEmet;             //  A true si l'émetteur peut être changé
      bool bUtiliseCarnAdr;          // true si le carnet d'adresses est utilisé
      bool bModeParametrage;         //A true si nous voulons avoir accès à l'écran des paramétrages des modèles, à false pour les courriers
      bool bProtegerModelesFournis;  //A true : Les modèles livrés ne peuvent pas être modifiés par l'utilisateur
      bool bMultiLangue;             //A true : Gestion de plusieurs langues
      bool bGererEnTeteEtPiedDePage; //A true : Gestion des en tête et pied de page dans le courrier
      GetValueOfVarEvent FctGetValueOfVar;  // Fonction CallBack qui sera appelée si != NULL
      GetDescriptionModele FctGetDescriptionModele; // Fonction CallBack qui permet de connaître la description d'un modèle
      TFctQueryActionModele FctQueryActionModele; //Fonction appelée pour demander la confirmation de l'action effectuée sur un modèle
      TFctActionModele FctActionModele; //Fonction appelée pour chaque action effectuée sur un modèle
      TFctModeleIsVisible FctModeleIsVisible; //Fonction appelée pour savoir si le modèle doit être affiché

      typedef bool __fastcall (__closure *TFctOnAfficheModele)(const AnsiString &aLogiciel,
                                                         const AnsiString &aCategorie,
                                                         const AnsiString &aLibelle);

      TContrainteTaille sContrainteTaille; //Contrainte de taille à appliquer lors de la saisie des modèles
      TList *lstColonnes;            //Configuration des colonnes de l'interfaçe

      AnsiString aLogicielDefaut;    //  Indique quel
      AnsiString aCategorieDefaut;   //     est le modèle qui sera sélectionné
      AnsiString aLibelleDefaut;     //        par défaut

   public :
      __fastcall tsConfigBPL();
      virtual __fastcall ~tsConfigBPL();
   };

struct TParamColCourrier
   {
   char szNomCol[50];
   TCol TypeColonne;
   short shWidth;
   bool bAjusterLargeur;
   TStringList *slList;
   int Ordre;
   };

class PACKAGE_OUTILS TColParametrable : public TCollectionItem
   {
   private:
      AnsiString m_aLibelleCol;
      TCol m_TypeColonne;
      bool m_bVisible;
      short m_shWidth;
      bool m_bAjusterLargeur;
      TStringList *m_slListe;
      int m_iOrdre;

      void __fastcall SetLibelleCol (const AnsiString aLibelle);
      void __fastcall SetTypeColonne (TCol TypeColonne);
      void __fastcall SetAjusterLargeur (bool bAjusterLargeur);
      void __fastcall SetListeParametrable(TStringList *slListeParametrable);

   protected:
      virtual AnsiString __fastcall GetDisplayName();

   public:
      virtual __fastcall TColParametrable(Classes::TCollection* Collection);
      virtual __fastcall ~TColParametrable(void);
      virtual void __fastcall Assign(Classes::TPersistent* Source);

   __published:
      __property AnsiString Libelle = {read=m_aLibelleCol, write=SetLibelleCol};
      __property bool Visible = {read=m_bVisible, write=m_bVisible, default = true};
      __property TCol TypeColonne = {read = m_TypeColonne, write = SetTypeColonne, default = colNonDefinie};
      __property short Width = {read = m_shWidth, write = m_shWidth, default = 50};
      __property bool AjusterLargeur = {read = m_bAjusterLargeur, write = SetAjusterLargeur, default = false};
      //C'est la position de la chaîne qui est mémorisée dans les courriers => ne pas changer l'ordre
      __property TStringList* ListeParametrable = {read = m_slListe, write = SetListeParametrable};
      __property int Ordre = {read = m_iOrdre, write = m_iOrdre};
   };

class CCourrier;
class TListColParametrables : public TCollection
   {
   private:
      CCourrier* m_Owner;

   protected:
      DYNAMIC Classes::TPersistent* __fastcall GetOwner(void);

   public:
      __fastcall TListColParametrables(CCourrier* AOwner);
      __property CCourrier* Owner = {read=m_Owner};
   public:
   };

typedef HWND (*FctGererCourriers)(HWND hApplicationMainFormHandle, HWND hParent,
                                  const tsConfigBPL &sConfig,
                                  eErrCourriers *NumErreur);

typedef void (*FctDesallouerEcran)(HWND *hEcran);

typedef unsigned long (*FctGetCoordDossier) ();

typedef void (*FctChangerCoorDoss)(int nCoorDoss);

typedef void (*FctChangerLangue)(IDLangue eLangue);

typedef void (*FctChangerOrientation)(IDOrientation eOrientation);

class PACKAGE_OUTILS CCourrier : public TCustomPanel
{
public:
   bool __fastcall Afficher(unsigned long NoCoord,
                            const AnsiString &aLogicielDefaut = EmptyStr,
                            const AnsiString &aCategorieDefaut = EmptyStr,
                            const AnsiString &aLibelleDefaut = EmptyStr
                            );

// Cette fonction est appelée lorsque l'écran "gérer courriers" est affiché
// ET que l'on doit changer les coordonné du dossier.
   void __fastcall ChangerCoorDoss (int nCoorDoss);

//     Le numéro 'nCoorDossier' permet de relier un dossier aux coordonnées du courrier
//     Les coordonnées correspondent à l'emetteur et au(x) destinataire(s) d'un courrier
//     La première fois que l'on rentre avec un dossier dans ce traitement, affecter 0
//     à nCoorDossier. Il faudra ensuite utiliser la fonction GetCoordDoss pour connaître
//     les coordonnées affecter à ce dossier.
   unsigned long __fastcall GetNoCoord();

 //     Donne la liste des courriers du logiciel en cours.
   bool __fastcall ListeCourriers(const AnsiString &aLogiciel,const AnsiString &aCategorie, TStringList *ListeDesCourriers);

   __fastcall CCourrier(TComponent* Owner);
   virtual __fastcall ~CCourrier();

private:
   unsigned long nNoCoord;
   AnsiString m_aLogicielDefaut;
   AnsiString m_aCategorieDefaut;
   AnsiString m_aLibelleDefaut;

   FctGererCourriers _GererCourriers;
   FctDesallouerEcran _DesallouerEcran;
   FctGetCoordDossier _GetCoordDossier;
   FctChangerCoorDoss _ChangerCoorDoss;
   FctChangerLangue _ChangerLangue;
   FctChangerOrientation _ChangerOrientation;

   IDLangue m_eLangue;
   IDOrientation m_eOrientation;
   bool m_bAffichageDemande;
   bool m_bUtiliseCarnAdr;
   bool m_bModeParametrage;
   bool m_bProtegerModelesFournis;
   bool m_bMultiLangue;
   bool m_bGererEnTeteEtPiedDePage;
   TContrainteTailleRichEdit *m_ContrainteTaille;
	TListColParametrables* m_ListCol;

   GetValueOfVarEvent FctGetValueOfVar;
   GetDescriptionModele FctGetDescriptionModele;
   TFctQueryActionModele m_FctQueryActionModele;
   TFctActionModele   m_FctActionModele;
   TFctModeleIsVisible m_FctModeleIsVisible;

   void __fastcall SetLogiciel(const AnsiString aLogiciel);
   void __fastcall DesallouerEcran();
   void __fastcall MyOnResize (System::TObject* Sender);
   void __fastcall SetModeParametrage(bool bModeParametrage);
   void __fastcall SetLangue(IDLangue eLangue);
   void __fastcall SetOrientation(IDOrientation eOrientation);

 protected:
   HWND       HandleForm;  // TForm utilisée pour remplir le panel conteneur.
   HANDLE hEditeur;
   AnsiString aFileNameEicEdito;
   AnsiString m_aLogiciel;
   AnsiString m_aCategorie;
   AnsiString m_aCategorieVariables;

   void __fastcall WMDestroy(TMessage &Msg);
   void __fastcall WMCreate(TMessage &Msg);
   BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER( WM_CREATE, TMessage, WMCreate)
    MESSAGE_HANDLER( WM_DESTROY, TMessage, WMDestroy)
   END_MESSAGE_MAP(TCustomPanel)

  __property bool ModeParametrage = {read = m_bModeParametrage, write = SetModeParametrage};

  __published:
  __property Align;
  __property Visible;
  __property AnsiString Logiciel = {read = m_aLogiciel, write = SetLogiciel};
  __property AnsiString Categorie = {read = m_aCategorie, write = m_aCategorie};

  // Nom des catégories de variables à utiliser (séparé par des points-virgules).
  // La catégorie précédée du caractère * est la catégorie par défaut.
  // Si la chaine est vide OU si elle ne contient que la catégorie par défaut => toutes les catégories seront accessibles
  __property AnsiString CategorieVariables = {read = m_aCategorieVariables, write = m_aCategorieVariables};
  __property bool MultiLangue = {read = m_bMultiLangue, write = m_bMultiLangue, default = false};
  __property IDLangue Langue = {read = m_eLangue, write = SetLangue, default = lngFRANCAIS};
  __property IDOrientation Orientation = {read = m_eOrientation, write = SetOrientation, default = eOrLibre};

  __property bool UtiliseCarnAdr = {read = m_bUtiliseCarnAdr, write = m_bUtiliseCarnAdr};
  __property bool ProtegerModelesFournis = {read = m_bProtegerModelesFournis, write = m_bProtegerModelesFournis, default = false};
  __property bool GererEnTeteEtPiedDePage = {read = m_bGererEnTeteEtPiedDePage, write = m_bGererEnTeteEtPiedDePage, default = true};
  __property TListColParametrables* Colonnes = {read=m_ListCol, write=m_ListCol, nodefault};
  __property TContrainteTailleRichEdit *Contraintes = {read=m_ContrainteTaille, write=m_ContrainteTaille};

  __property GetValueOfVarEvent    OnGetValueOfVar        = {read=FctGetValueOfVar       , write=FctGetValueOfVar       };
  __property GetDescriptionModele  OnGetDescriptionModele = {read=FctGetDescriptionModele, write=FctGetDescriptionModele}; // Fonction CallBack qui permet de connaître la description d'un modèle
  __property TFctQueryActionModele OnQueryActionModele    = {read=m_FctQueryActionModele , write=m_FctQueryActionModele }; //Evénement appelé pour chaque action effectuée sur un modèle
  __property TFctActionModele      OnActionModele         = {read=m_FctActionModele      , write=m_FctActionModele      }; //Evénement appelé pour chaque action effectuée sur un modèle
  __property TFctModeleIsVisible   OnModeleIsVisible      = {read=m_FctModeleIsVisible   , write=m_FctModeleIsVisible   }; //Evénement appelé pour savoir si le modèle doit être affiché
  };

#endif
